package app.vendorportal.web.interceptor;

import app.vendorportal.domain.vendor.VendorUser;
import app.vendorportal.service.SecurityValidator;
import app.vendorportal.web.SecureSessionConstants;
import app.vendorportal.web.SiteContext;
import core.framework.util.StringUtils;
import core.framework.web.site.ControllerHelper;
import core.framework.web.site.session.SecureSessionContext;
import core.framework.web.site.url.URLBuilder;

import org.apache.http.HttpStatus;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author neo
 */
public class LoginRequiredInterceptor extends HandlerInterceptorAdapter {

    private SecureSessionContext secureSessionContext;

    private SiteContext siteContext;

    private SecurityValidator securityValidator;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            LoginRequired loginRequired = ControllerHelper.findMethodOrClassLevelAnnotation(handler, LoginRequired.class);
            if (null != loginRequired && !loggedIn() && (isAjaxRequest(request) || isMultiPartFile(request))) {
                // TODO:in local need to redirect to intranet
                response.setStatus(HttpStatus.SC_UNAUTHORIZED);
                response.getWriter().write("The session is time out,please login again!");
                response.flushBuffer();
                return false;
            }

            if (null != loginRequired && !loggedIn() && !isAjaxRequest(request)) {
                redirectToSpecifiedPage(request, response, "/login?preRequestUrl=" + securityValidator.validateRedirectUrl(request.getPathInfo()));
                return false;
            }

            if (null != loginRequired && loggedIn() && !siteContext.getRelativeUrl().startsWith("/home")) {
                return isAgreeTerm(request, response);
            }
        }
        return true;
    }

    boolean loggedIn() {
        Boolean loggedIn = secureSessionContext.get(SecureSessionConstants.LOGGED_IN);
        return Boolean.TRUE.equals(loggedIn);
    }

    private boolean isAgreeTerm(HttpServletRequest request, HttpServletResponse response) {
        VendorUser user = siteContext.getUser();
        if (null != user && !user.getAgreeTerm()) {
            redirectToSpecifiedPage(request, response, "/home");
            return false;
        }
        return true;
    }

    private boolean redirectToSpecifiedPage(HttpServletRequest request, HttpServletResponse response, String specifiedURL) {
        URLBuilder builder = new URLBuilder();

        // TODO(B) builder.setContextPath(deploymentSettings.getDeploymentContext());
        builder.setContextPath(request.getContextPath());

        builder.setLogicalURL(specifiedURL);
        response.setStatus(302);
        response.setHeader("Location", builder.buildRelativeURL());
        return true;
    }

    private boolean isAjaxRequest(HttpServletRequest request) {
        return "XMLHttpRequest".equalsIgnoreCase(request.getHeader("X-Requested-With"));
    }

    private boolean isMultiPartFile(HttpServletRequest request) {
        return StringUtils.hasText(request.getContentType()) && request.getContentType().startsWith("multipart/form-data;");
    }

    @Inject
    public void setSecureSessionContext(SecureSessionContext secureSessionContext) {
        this.secureSessionContext = secureSessionContext;
    }

    // @Inject
    // public void setDeploymentSettings(DeploymentSettings deploymentSettings) {
    // this.deploymentSettings = deploymentSettings;
    // }

    @Inject
    public void setSiteContext(SiteContext siteContext) {
        this.siteContext = siteContext;
    }

    @Inject
    public void setSecurityValidator(SecurityValidator securityValidator) {
        this.securityValidator = securityValidator;
    }

}
